﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// NotReviewedButNeeded
#pragma once

#include "GcmpGeometryInterface.h"
#include "OwnerPtr.h"
#include "GbmpConstants.h"
#include "MultiSectionLoftEnums.h"
#include "IFaceToPathProfileIndexMap.h"
#include "GcmpApiDeclaration.h"
#include "IBodyFactory.h"

namespace gcmp
{
    class Vector2i;
    class Vector2d;
    class Vector3d;
    class Coordinate3d;
    class ILine2d;
    class ICurve2d;
    class ICurve3d;
    class IPolyCurve;
    class IPolyCurve3d;
    class IPolygon;
    class ISurface;
    class IFace;
    class IBody;
    class IMesh;
    class IPlane;
    class IGraphicsNodeIdAsker;

    class GCMP_GEOMETRY_INTERFACE_EXPORT GmBodyBuilder
    {
    public:
        /// \brief 构造圆柱体
        /// \param bottomCenter   底面圆心
        /// \param topCenter      顶面圆心
        /// \param radius         半径
        /// \return 圆柱体
        static OwnerPtr<IBody> CreateSolidCylinder(
            const Vector3d &bottomCenter,
            const Vector3d &topCenter,
            double radius);

        /// \brief 构造长方体
        /// \param coordinate   局部坐标系（原点为长方体顶点）
        /// \param dimension    长，宽，高（要求大于零）
        /// \return 长方体
        static OwnerPtr<IBody>  CreateSolidCuboid(
            const Coordinate3d &coordinate,
            const Vector3d &dimension);

        /// \brief 构造球体
        /// \param center   球心
        /// \param unitAxis 单位轴向（平面的法向）
        /// \param radius   半径
        /// \return 球体
        static OwnerPtr<IBody> CreateSphereBody(
            const Vector3d &center,
            const Vector3d &unitAxis,
            double radius);

        /// \brief 构造圆锥体
        /// \param bottomCenter 底面圆心
        /// \param topPos 顶点
        /// \param bottomRadius 底面半径
        /// \return 圆锥体
        static OwnerPtr<IBody> CreateConeBody(
            const Vector3d &bottomCenter,
            const Vector3d &topPos,
            double bottomRadius);

        /// \brief 构造圆台体
        /// \param bottomCenter 底面圆心
        /// \param topPos （圆锥的）顶点
        /// \param radius 底面半径
        /// \param height 圆台高度
        /// \return 圆台体
        static OwnerPtr<IBody> CreateTruncedConeBody(
            const Vector3d &bottomCenter,
            const Vector3d &topPos,
            double radius,
            double height);

        /// \brief 构造圆台体
        /// \param bottomCenter 底面圆心
        /// \param bottomRadius 底面半径
        /// \param topCenter 顶面圆心
        /// \param topRadius 顶面半径
        /// \return 圆台体
        static OwnerPtr<IBody> CreateTruncedConeBody(
            const Vector3d &bottomCenter,
            double bottomRadius,
            const Vector3d &topCenter,
            double topRadius);

        /// \brief 构造棱锥体
        /// \param apex 顶点
        /// \param basePoints 底面多边形顶点
        /// \return 棱锥体
        static OwnerPtr<IBody> CreatePyramidBody(
            const Vector3d &apex,
            const std::vector<Vector3d> &basePoints);

        /// \brief 构造棱台体
        /// \param bottomPoints 底面顶点坐标
        /// \param topPoints    顶面顶点坐标
        /// \param verticesMap  上下面顶点的对应, Vector2i的X分量表示bottomPoints的顶点索引, Y分量topPoints顶点索引, x,y分量构成的序列前后值都是相同或者相邻的顶点索引.
        /// \return 棱台体
        static OwnerPtr<IBody> CreatePrismBody(
            const std::vector<Vector3d> &bottomPoints,
            const std::vector<Vector3d> &topPoints,
            const std::vector<Vector2i> &verticesMap);

        /// \brief 构造椭球体
        /// \param pos 椭球体中心点位置
        /// \param majorAxis 椭圆长半轴方向
        /// \param majorRad 长半轴长度
        /// \param minorRad 短半轴长度
        /// \return 椭球体
        static OwnerPtr<IBody> CreateEllipsoidBody(
            const Vector3d &pos,
            const Vector3d &majorAxis,
            double majorRad,
            double minorRad);

        /// \brief 构造椭球体
        /// \param center 椭球体中心坐标系
        /// \param axisX X轴方向
        /// \param axisY Y轴方向
        /// \param xRad 椭圆x轴方向半径
        /// \param yRad 椭圆y轴方向半径
        /// \param zRad 椭圆z轴方向半径
        /// \param retBody 椭球体
        /// \return 错误码
        static GeometryErrorCode CreateEllipsoidBody(
            const Vector3d &center,
            const Vector3d &axisX,
            const Vector3d &axisY,
            double xRad,
            double yRad,
            double zRad,
            OwnerPtr<IBody>& retBody);

        /// \brief 构造圆环体
        /// \param pos 圆环体中心位置
        /// \param axis 圆环体中心轴方向
        /// \param bodyRadius 圆环体半径
        /// \param sectionRadius 圆环体截面半径
        /// \return 圆环体
        static OwnerPtr<IBody> CreateTorusBody(
            const Vector3d &pos,
            const Vector3d &axis,
            double bodyRadius,
            double sectionRadius);

        /// \brief 构造棱柱体（正多边形）
        /// \param centerPt 正多边形外接圆圆心
        /// \param radius 正多边形外接圆半径
        /// \param n 正多边形边数
        /// \param direction 拉伸方向
        /// \param length 拉伸距离，不允许为0，正值为沿拉伸正方向，负值为沿拉伸反方向
        /// \return 棱柱体
        static OwnerPtr<IBody> CreateRegularPrismBody(
            const Vector3d &centerPt,
            double radius,
            int n,
            const Vector3d &direction,
            double length);

        /// \brief 构造椭圆锥体,需保证输入椭圆长半轴方向与中心轴方向垂直
        /// \param centerPt 椭圆中心点
        /// \param majorAxis 椭圆长半轴方向
        /// \param majorRad 椭圆长半轴长度
        /// \param minorRad 椭圆短半轴长度
        /// \param direction 椭圆锥中心轴方向
        /// \param height 椭圆锥高度
        /// \return 椭圆锥体
        static OwnerPtr<IBody> CreateEllipseConeBody(
            const Vector3d &centerPt,
            const Vector3d &majorAxis,
            double majorRad,
            double minorRad,
            const Vector3d &direction,
            double height);

        /// \brief 根据三维空间点列表构建一个平面,垂直平面拉伸成体;
        /// \param points    空间点列表
        /// \param length    拉伸长度
        /// \return 拉伸体
        static OwnerPtr<IBody> CreateExtrudeBodyByPoints(
            const std::vector<Vector3d> &points,
            double length);

        /// \brief 根据三维空间点列表构建一个平面,垂直平面拉伸成体;需保证点列表共面;
        /// \param points          空间点列表
        /// \param unitDirection   拉伸方向
        /// \param length          拉伸长度
        /// \return 拉伸体
        static OwnerPtr<IBody> CreateExtrudeBodyByPoints(
            const std::vector<Vector3d> &points,
            const Vector3d &unitDirection,
            double length);

        /// \brief 构造拉伸体
        /// \param coordinate     局部坐标系
        /// \param pSection       草图截面
        /// \param unitDirection  拉伸方向
        /// \param startOffset    起始端偏移值
        /// \param endOfffset     终止端偏移值
        /// \return 拉伸体
        static OwnerPtr<IBody>  CreateExtrudeBody(
            const Coordinate3d &coordinate,
            const IPolygon *pSection,
            const Vector3d&  unitDirection,
            double startOffset,
            double endOfffset,
            OwnerPtr<IExtrudeFaceToPathProfileIndexMap>& opFaceToPathProfileIndexMap = OwnerPtr<IExtrudeFaceToPathProfileIndexMap>(nullptr));

        /// \brief 构造拉伸体(待废弃)
        /// \param coordinate        局部坐标系
        /// \param pSection          草图截面
        /// \param unitDirection     拉伸方向
        /// \param startOffset       起始端偏移值
        /// \param endOfffset        终止端偏移值
        /// \param sketchCrvIndices  草图线的唯一序号
        /// \return 拉伸体
        static OwnerPtr<IBody> CreateExtrudeBody(
            const Coordinate3d& coordinate,
            const IPolygon* pSection,
            const Vector3d& direction,
            double startOffset,
            double endOffset,
            const std::vector<Int32>& sketchCrvIndices);

        /// \brief 构造拉伸体
        /// \param pGraphicsNodeIdAsker 拓扑命名查询器
        /// \param coordinate           局部坐标系
        /// \param pSection             草图截面
        /// \param unitDirection        拉伸方向
        /// \param startOffset          起始端偏移值
        /// \param endOfffset           终止端偏移值
        /// \param sketchCrvIndices     草图线的唯一序号
        /// \return 拉伸体
        static OwnerPtr<IBody> CreateExtrudeBody(
            IGraphicsNodeIdAsker* pGraphicsNodeIdAsker,
            const Coordinate3d& coordinate,
            const IPolygon* pSection,
            const Vector3d& direction,
            double startOffset,
            double endOffset,
            const std::vector<Int32>& sketchCrvIndices);

        /// \brief 构造拉伸体
        /// \param pIFace          拓扑面
        /// \param unitDirection   拉伸方向
        /// \param length          拉伸长度
        /// \return 拉伸体
        static OwnerPtr<IBody> CreateExtrudeBody(
            const IFace* pIFace,
            const Vector3d&  unitDirection,
            double length
        );

        /// \brief 根据三维空间三个点 构建一个圆弧, offset出一个共圆心的新圆弧, 两圆弧形成闭合多边形平面, 垂直平面拉伸成体
        /// \param firstPoint         起始点坐标
        /// \param endPoint           终止点坐标
        /// \param referencePoint     参考点坐标
        /// \param thickness          实体厚度
        /// \param length             拉伸高度
        /// \return 拉伸体
        static OwnerPtr<IBody> CreateExtrudeBodyByArc(
            const Vector3d &firstPoint,
            const Vector3d &endPoint,
            const Vector3d &referencePoint,
            double thickness,
            double length);

        
        /// \brief     构造沿一串相互连接的空间曲线拉伸成的拉伸壳体
        /// \param const IPlane *pPlane  草图所在的平面坐标系，拉伸的基准坐标系
        /// \param const IPolyCurve *pCurve  拉伸轮廓
        /// \param const Vector3d &direction 拉伸方向，不允许平行于基准坐标系XY平面
        /// \param double length                   拉伸距离，不能为0
        /// \return    拉伸壳体
        static OwnerPtr<IBody> CreateExtrudeShellBody(
            const IPlane *pPlane,
            const IPolyCurve *pCurve,
            const Vector3d &direction,
            double length) ;

        /// \brief  线框体拉伸成壳体，壳体拉伸成实体
        /// \param[in] pBody  线框体或壳体
        /// \param[in] direction  拉伸方向
        /// \param[in] length  拉伸长度
        /// \param[out] opResultBody  拉伸的壳体或实体
        /// \return 错误码
        static GeometryErrorCode CreateExtrudeBody(
            const IBody* pBody,
            const Vector3d& direction,
            double length,
            OwnerPtr<IBody>& opResultBody);

        /// \brief   线框体旋转成壳体，壳体旋转成实体
        /// \param[in] pBody  线框体或壳体
        /// \param[in] pAxis3d  带方向的旋转轴
        /// \param[in] revolvedAngle  旋转角度，弧度表示
        /// \param[out] opResultBody  旋转的实体
        /// \return 错误码
        static GeometryErrorCode CreateRevolveBody(
            const IBody* pBody,
            const ILine3d* pAxis3d,
            double revolvedAngle,
            OwnerPtr<IBody>& opResultBody);

        /// \brief 构造旋转体（截面多边形和旋转轴必须在一个平面上）
        /// \param coordinate   局部坐标系
        /// \param pSection     草图截面
        /// \param pAxis2d      带方向的旋转轴
        /// \param startAngle   起始旋转角度（弧度表示）
        /// \param endAngle     终止旋转角度（弧度表示）
        /// \return 旋转体
        static OwnerPtr<IBody> CreateRevolveBody(
            const Coordinate3d& coordinate,
            const IPolygon* pSection,
            const ILine2d* pAxis2d,
            double startAngle,
            double endAngle);

        /// \brief 构造旋转体（截面多边形和旋转轴必须在一个平面上）
        /// \param pGraphicsNodeIdAsker 拓扑命名查询器
        /// \param coordinate       局部坐标系
        /// \param pSection         截面草图
        /// \param pAxis2d          带方向的旋转轴
        /// \param startAngle       起始旋转角度（弧度表示）
        /// \param endAngle         终止旋转角度（弧度表示）
        /// \param sketchCrvIndices 草图线的唯一序号
        /// \return 旋转体
        static OwnerPtr<IBody> CreateRevolveBody(
            IGraphicsNodeIdAsker* pGNodeIdAsker,
            const Coordinate3d& coordinate,
            const IPolygon* pSection,
            const ILine2d* pAxis2d,
            double startAngle,
            double endAngle,
            const std::vector<Int32>& sketchCrvIndices);

        /// \brief  壳体扫掠成实体
        /// \param[in] pBody  扫描轮廓：线框体（wire）或壳体(sheet)
        /// \param[in] pSpine  一组至少G0连接的空间脊线: 线框体(wire)
        /// \param[in] options  扫描选项
        /// \param[out] opResultBody  扫描的实体
        /// \return 错误码
        static GeometryErrorCode CreateSweepBody(
            const IBody* pBody,
            const IBody* pSpine,
            const SweepOptions& options,
            OwnerPtr<IBody>& opResultBody);

        /// \brief 构造多段扫描体
        /// \param opSection   草图截面，其局部坐标系确定：Y方向对应路径坐标系的Z轴，Z方向对应扫描路径的切线方向
        /// \param opSpines    扫描路径线，目前只支持直线和圆弧
        /// \param coordinate  扫描路径线所在的坐标系，路径位于XOY面上
        /// \return 多段扫描体
        static OwnerPtr<IBody> CreateSweepBody(
            const OwnerPtr<IPolygon>& opSection,
            const std::vector<OwnerPtr<ICurve2d>>& opSpines,
            const Coordinate3d& coordinate,
            OwnerPtr<ISweepFaceToPathProfileIndexMap>& opSweepFaceToPathProfileIndexMap = OwnerPtr<ISweepFaceToPathProfileIndexMap>(nullptr));

        /// \brief 构造多段扫略体（带拓扑命名）
        /// \param pGraphicsNodeIdAsker      拓扑命名查询器
        /// \param pSection                  草图截面，其局部坐标系确定：Y方向对应路径坐标系的Z轴，Z方向对应扫略路径的切线方向
        /// \param pSpines                   扫略路径线，目前只支持直线和圆弧
        /// \param coordinate                扫略路径线所在的坐标系，路径位于XOY面上
        /// \param sketchCrvIndices          草图线的唯一序号
        /// \param pathCrvIndices            扫略路径的唯一序号
        /// \return 多段扫略体
        static OwnerPtr<IBody> CreateSweepBody(
            IGraphicsNodeIdAsker *pGNodeIdAsker,
            const IPolygon* pSection,
            const IPolyCurve* pSpines,
            const Coordinate3d& coordinate,
            const std::vector<Int32>& sketchCrvIndices,
            const std::vector<Int32>& pathCrvIndices);

        /// \brief 构造多段扫略体（带拓扑命名）
        /// \param pGraphicsNodeIdAsker      拓扑命名查询器
        /// \param pSection                  草图截面（与路径切向垂直）
        /// \param pSpines                   扫略路径(一组至少G0连接的空间曲线，目前只支持直线和圆弧)
        /// \param referenceDirection        参考方向
        /// \param sketchCrvIndices          草图线的唯一序号
        /// \param pathCrvIndices            扫略路径的唯一序号
        /// \param type   扫描类型
        /// \return 多段扫略体
        static OwnerPtr<IBody> CreateSweepBody(
            IGraphicsNodeIdAsker *pGNodeIdAsker,
            const IPolygon* pSection,
            const std::vector<const ICurve3d*>& pSpines,
            const Vector3d& referenceDirection,
            const std::vector<Int32>& sketchCrvIndices,
            const std::vector<Int32>& pathCrvIndices,
            SweepType type = SweepType::Perpendicular);

        /// \brief 构造多段扫略体
        /// \param pSection                  草图截面（与路径切向垂直）
        /// \param pSpines                   扫略路径(一组至少G0连接的空间曲线，目前只支持直线和圆弧)
        /// \param referenceDirection        参考方向
        /// \param type   扫描类型
        /// \param opSweepFaceToPathProfileIndexMap  Face索引与路径和轮廓索引的关系数据
        static OwnerPtr<IBody> CreateSweepBody(
            const OwnerPtr<IPolygon>& opSection,
            const std::vector<const ICurve3d*>& opSpines,
            const Vector3d& referenceDirection,
            SweepType type = SweepType::Perpendicular,
            OwnerPtr<ISweepFaceToPathProfileIndexMap>& opSweepFaceToPathProfileIndexMap = OwnerPtr<ISweepFaceToPathProfileIndexMap>(nullptr));

        /// \brief 由给定的底平面和顶平面创建一个融合体（带拓扑命名）
        /// \param pGraphicsNodeIdAsker       拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param bottomCoordinate           底草图截面所在局部坐标系
        /// \param pBottomSection             底草图截面（可多个环）
        /// \param topCoordinate              顶草图截面所在局部坐标系
        /// \param pTopSection                顶草图截面（可多个环）
        /// \param topSketchCurveIndices      顶面草图线的唯一序号
        /// \param bottomSketchCurveIndices   底面草图线的唯一序号
        /// \param verticesMap                顶底草图截面顶点的对应, 是一个二维数组：外面的数组索引是两个轮廓的环的索引；里面的数组中，Vector2i的X分量表示底面的环的顶点索引, Y分量顶面的环的顶点索引,
        ///                                   x,y分量构成的序列前后值都是相同或者相邻的顶点索引；约定底部轮廓的环的顶点索引从0开始（顶部轮廓的环的顶点索引是可以不从0开始的）
        ///                                   比如底部轮廓的第一个环上有4个点，顶部轮廓的第一个环上有3个点，第一个环合法的定点map可以是(0,0), (1,0), (2,1), (3,2)；当然也可以是(0,2), (1,0), (2,0), (3,1)等等
        /// \return 融合体
        static OwnerPtr<IBody> CreateBlendBody(
            IGraphicsNodeIdAsker* pGNodeIdAsker,
            const Coordinate3d& bottomPlane,
            const IPolygon* pBottomSection,
            const Coordinate3d& topPlane,
            const IPolygon* pTopSection,
            const std::vector<std::vector<int>>& topSketchCurveIndices,
            const std::vector<std::vector<int>>& bottomSketchCurveIndices,
            const std::vector<std::vector<Vector2i>>& verticesMap
        );

        /// \brief 由给定的底平面和顶平面创建一个融合体（不带拓扑命名，仅返回拓扑关系Map）
        /// \param[in] bottomPlane            底平面坐标系
        /// \param[in] pBottomSection         底平面轮廓，可多个环
        /// \param[in] topPlane               顶平面坐标系
        /// \param[in] pTopSection            顶平面轮廓，可多个环
        /// \param[in] verticesMap            顶底草图截面顶点的对应, 是一个二维数组：外面的数组索引是两个轮廓的环的索引；里面的数组中，Vector2i的X分量表示底面的环的顶点索引, Y分量顶面的环的顶点索引,
        ///                                   x,y分量构成的序列前后值都是相同或者相邻的顶点索引；约定底部轮廓的环的顶点索引从0开始（顶部轮廓的环的顶点索引是可以不从0开始的）
        ///                                   比如底部轮廓的第一个环上有4个点，顶部轮廓的第一个环上有3个点，第一个环合法的定点map可以是(0,0), (1,0), (2,1), (3,2)；当然也可以是(0,2), (1,0), (2,0), (3,1)等等
        /// \param[out] opFaceToPathProfileIndexMap   Face索引与顶底截面轮廓索引的关系数据
        /// \return 融合体
        static OwnerPtr<IBody> CreateBlendBody(
            const Coordinate3d& bottomPlane,
            const IPolygon* pBottomSection,
            const Coordinate3d& topPlane,
            const IPolygon* pTopSection,
            const std::vector<std::vector<Vector2i>>& verticesMap,
            OwnerPtr<IBlendFaceToPathProfileIndexMap>& opFaceToPathProfileIndexMap
        );

        /// \brief  由顶面和底面轮廓生成放样融合体
        ///         由于需要顶点IVertex的匹配关系，所以需要开启拓扑点生成之后这个接口才有效（可以设置gbmp_gcmp_behavior_config的配置EnableVertexGeneration不为0）
        /// \param[in] pTopBody  顶面轮廓（壳体或线框体）
        /// \param[in] pBottomBody  底面轮廓（壳体或线框体，需要和顶面轮廓类型一致）
        /// \param[in] options  顶面和底面放样融合选项
        ///  options.DistEpsilon  距离容差
        ///  options.Type  放样类型，目前支持Default类型（不调整轮廓位置）和Perpendicular类型（将轮廓调整为和脊线垂直）
        ///  options.Spine  脊线，可以为默认空指针，为空时放样类型不起作用
        ///  options.LoftVerticesMap  两截面顶点匹配关系，如果顶面和底面顶点数相同，可仅指定起始顶点匹配关系
        /// \param[out] opResultBody  创建的放样融合体
        /// \return 错误码
        static GeometryErrorCode CreateBlendBody(
            const IBody* pTopBody,
            const IBody* pBottomBody,
            const gcmp::BlendOptions& options,
            OwnerPtr<IBody>& opResultBody
        );

        /// \brief    带脊线的放样体
        /// \param pGNodeIdAsker     拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param  pStartSection             起始端草图截面，允许多个环，需要保持和pEndSection对应相同
        /// \param  pEndSection               终止端草图截面，允许多个环，需要保持和pStartSection对应相同
        /// \param  pSpines                   放样路径
        /// \param  referenceDirection        参考向量
        /// \param  endSketchCurveIndices     尾端草图线的唯一序号，用于拓扑命名，如pEndSection终止端草图截面的第一个环上有3条曲线，则第一个环建议的数组为{0,1,2},这个数组里的值是用户维护和指定的，也可以指定为其他不相同的值
        /// \param  startSketchCurveIndices   首端草图线的唯一序号，用于拓扑命名，如pStartSection起始端草图截面的第一个环上有4条曲线，则第一个环建议的数组为{0,1,2,3},这个数组里的值是用户维护和指定的，也可以指定为其他不相同的值
        /// \param verticesMap                起始终止草图截面顶点的对应, 是一个二维数组：外面的数组索引是两个轮廓的环的索引；里面的数组中，Vector2i的X分量表示底面的环的顶点索引, Y分量顶面的环的顶点索引,
        ///                                   x,y分量构成的序列前后值都是相同或者相邻的顶点索引；约定起始端草图截面的环的顶点索引从0开始（终止端端草图截面的环的顶点索引是可以不从0开始的）
        ///                                   比如起始端草图截面的第一个环上有4个点，终止端草图截面的第一个环上有3个点，第一个环合法的定点map可以是(0,0), (1,0), (2,1), (3,2), (0,0)；当然也可以是(0,2), (1,0), (2,0), (3,1), (0,2)等等
        /// \param type 放样类型
        /// \return 放样融合体
        static OwnerPtr<IBody> CreateSweptLoftBody(
            IGraphicsNodeIdAsker*                       pGNodeIdAsker,
            const IPolygon*                             pStartSection,
            const IPolygon*                             pEndSection,
            const std::vector<const ICurve3d*>&         pSpines,
            const Vector3d&                             referenceDirection,
            const std::vector<std::vector<int>>&        endSketchCurveIndices,
            const std::vector<std::vector<int>>&        startSketchCurveIndices,
            const std::vector<std::vector<Vector2i>>&   verticesMap,
            gcmp::LoftType type = gcmp::LoftType::Perpendicular
        );

        /// \brief  带脊线的放样体
        ///         Coordinate应满足:
        ///             1、原点应与路径的始末点重合
        ///             2、Z轴与路径的始末切矢的夹角theta<(90-Constants::ANGLE_EPS)
        ///             3、为单位正交右手系
        ///         Polygon应满足:
        ///             1、polygon在Coordinate的XOY平面上
        ///             2、第一个环是逆时针的 且polygon是单连通的，不支持多连通polygon
        /// \param  pGNodeIdAsker             拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param  pBottomSection            起始端草图截面，允许多个环，需要保持和pTopSection对应相同
        /// \param  pTopSection               终止端草图截面，允许多个环，需要保持和pBottomSection对应相同
        /// \param  bottomCoordinate          起始坐标系
        /// \param  topCoordinate             终止坐标系
        /// \param  pSpines                   放样路径
        /// \param  bottomSketchCurveIndices  首端草图线的唯一序号，用于拓扑命名，如pBottomSection起始端草图截面的第一个环上有4条曲线，则第一个环建议的数组为{0,1,2,3},这个数组里的值是用户维护和指定的，也可以指定为其他不相同的值
        /// \param  topSketchCurveIndices     尾端草图线的唯一序号，用于拓扑命名，如pTopSection终止端草图截面的第一个环上有3条曲线，则第一个环建议的数组为{0,1,2},这个数组里的值是用户维护和指定的，也可以指定为其他不相同的值
        /// \param verticesMap                起始终止草图截面顶点的对应, 是一个二维数组：外面的数组索引是两个轮廓的环的索引；里面的数组中，Vector2i的X分量表示底面的环的顶点索引, Y分量顶面的环的顶点索引,
        ///                                   x,y分量构成的序列前后值都是相同或者相邻的顶点索引；约定起始端草图截面的环的顶点索引从0开始（终止端端草图截面的环的顶点索引是可以不从0开始的）
        ///                                   比如起始端草图截面的第一个环上有4个点，终止端草图截面的第一个环上有3个点，第一个环合法的定点map可以是(0,0), (1,0), (2,1), (3,2), (0,0)；当然也可以是(0,2), (1,0), (2,0), (3,1), (0,2)等等
        /// \return 放样融合体
        static OwnerPtr<IBody> CreateSweptLoftBody(
            IGraphicsNodeIdAsker*                       pGNodeIdAsker,
            const IPolygon*                             pBottomSection,
            const IPolygon*                             pTopSection,
            const gcmp::Coordinate3d&                   bottomCoordinate,
            const gcmp::Coordinate3d&                   topCoordinate,
            const std::vector<const ICurve3d*>&         pSpines,
            const std::vector<std::vector<int>>&        bottomSketchCurveIndices,
            const std::vector<std::vector<int>>&        topSketchCurveIndices,
            const std::vector<std::vector<Vector2i>>&   verticesMap
        );

        /// \brief  由多截面轮廓生成放样体
        /// \param[in] pBodies  截面轮廓（线框体或壳体，需要类型相同）
        /// \param[in] options  多截面放样选项
        /// \param[out] opResultBody  创建的放样体
        /// \return 错误码
        static GeometryErrorCode CreateMultiSectionLoftBody(
            const std::vector<const IBody*>& pBodies,
            const MultiSectionLoftOptions& options,
            OwnerPtr<IBody>& opResultBody);

        /// \brief 创建多截面放样体（使用引导线、自动计算顶点匹配关系）
        ///
        /// 可参考https://km.glodon.com/pages/viewpage.action?pageId=37652643
        /// \param[out] pGraphicsNodeIdAsker  拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param[in]  planes                截面坐标系
        /// \param[in]  sections              截面多边形
        /// \param[in]  guides                引导线
        /// \param[in]  isDevidedByGuideCurve 引导线是否分割面(引导线是否为边线)
        /// \param[in]  mode                  顶点匹配模式
        /// \param[in]  minSegmentLength      极小段距离(参考值1)
        /// \param[in]  distEpsilon           距离容差(参考值Constants::LENGTH_EPS)
        /// \param[out] pErrorCode            错误码
        /// \param[out] opFaceToPathProfileIndexMap  Face索引与两侧截面轮廓索引的关系数据
        /// \return 多截面放样体
        static OwnerPtr<IBody> CreateMultiSectionLoftBody(
            IGraphicsNodeIdAsker*                  pGraphicsNodeIdAsker,
            const std::vector<Coordinate3d>&       planes,
            const std::vector<const IPolygon*>&    sections,
            const std::vector<const ICurve3d*>&    guides,
            bool                                   isDevidedByGuideCurve,
            const MultiSectionLoftVertexMatchMode& mode,
            double                                 minSegmentLength,
            double                                 distEpsilon,
            MultiSectionLoftErrorCode*             pErrorCode = nullptr,
            OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>& opFaceToPathProfileIndexMap = OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>(nullptr)
        );

        /// \brief 创建多截面放样体（使用引导线、指定顶点匹配关系）
        ///
        /// 可参考https://km.glodon.com/pages/viewpage.action?pageId=37652643
        /// \param[out] pGraphicsNodeIdAsker  拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param[in]  planes                截面坐标系
        /// \param[in]  sections              截面多边形
        /// \param[in]  guides                引导线
        /// \param[in]  isDevidedByGuideCurve 引导线是否分割面(引导线是否为边线)
        /// \param[in]  verticesMap           顶点匹配关系
        /// verticesMap 截面顶点匹配关系, 是一个二维数组, 必须封闭：
        /// 外面的数组索引是各组匹配关系的索引；
        /// 里面的数组索引是各个轮廓的环的索引；
        /// 里面的数组的值是相同或者相邻的顶点索引；
        /// 比如底部轮廓的第一个环上有3个点，中部轮廓的第一个环上有3个点，顶部轮廓的第一个环上有3个点，
        /// 第一个环合法的定点map可以是(0,0,0), (1,1,1), (2,2,2), (0,0,0)；
        /// 当然也可以是(0,1,0), (1,2,1), (2,0,2), (0,1,0)等等；
        /// \param[in]  minSegmentLength      极小段距离(参考值1)
        /// \param[in]  distEpsilon           距离容差(参考值Constants::LENGTH_EPS)
        /// \param[out] pErrorCode            错误码
        /// \param[out] opFaceToPathProfileIndexMap  Face索引与两侧截面轮廓索引的关系数据
        /// \return 多截面放样体
        static OwnerPtr<IBody> CreateMultiSectionLoftBody(
            IGraphicsNodeIdAsker*                pGraphicsNodeIdAsker,
            const std::vector<Coordinate3d>&     planes,
            const std::vector<const IPolygon*>&  sections,
            const std::vector<const ICurve3d*>&  guides,
            bool                                 isDevidedByGuideCurve,
            const std::vector<std::vector<int>>& verticesMap,
            double                               minSegmentLength,
            double                               distEpsilon,
            MultiSectionLoftErrorCode*             pErrorCode = nullptr,
            OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>& opFaceToPathProfileIndexMap = OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>(nullptr)
        );

        /// \brief 创建多截面放样体（使用引导线、闭合点）
        ///
        /// 可参考https://km.glodon.com/pages/viewpage.action?pageId=37652643
        /// \param[out] pGraphicsNodeIdAsker  拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param[in]  planes                截面坐标系
        /// \param[in]  sections              截面多边形
        /// \param[in]  guides                引导线
        /// \param[in]  isDevidedByGuideCurve 引导线是否分割面(引导线是否为边线)
        /// \param[in]  closedPoints          闭合点
        /// closedPoints 闭合点, 是一个一维数组：
        /// 数组索引是各个轮廓的环的索引；
        /// 数组的值是轮廓的环上顶点索引和顶点参数的数值对；
        /// 比如底部轮廓的第一个环上有3个点，中部轮廓的第一个环上有3个点，顶部轮廓的第一个环上有3个点，
        /// 合法的闭合点可以是(0,0.0), (0,0.0), (0,0.0)；
        /// 当然也可以是(0,0.0), (1,0.0), (2,0.0)等等；
        /// \param[in]  mode                  顶点匹配模式
        /// \param[in]  minSegmentLength      极小段距离(参考值1)
        /// \param[in]  distEpsilon           距离容差(参考值Constants::LENGTH_EPS)
        /// \param[out] pErrorCode            错误码
        /// \param[out] opFaceToPathProfileIndexMap  Face索引与两侧截面轮廓索引的关系数据
        /// \return 多截面放样体
        static OwnerPtr<IBody> CreateMultiSectionLoftBody(
            IGraphicsNodeIdAsker*                      pGraphicsNodeIdAsker,
            const std::vector<Coordinate3d>&           planes,
            const std::vector<const IPolygon*>&        sections,
            const std::vector<const ICurve3d*>&        guides,
            bool                                       isDevidedByGuideCurve,
            const std::vector<std::pair<int, double>>& closedPoints,
            const MultiSectionLoftVertexMatchMode&     mode,
            double                                     minSegmentLength,
            double                                     distEpsilon,
            MultiSectionLoftErrorCode*             pErrorCode = nullptr,
            OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>& opFaceToPathProfileIndexMap = OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>(nullptr)
        );

        /// \brief 创建多截面放样体（自动计算顶点匹配关系）
        ///
        /// 可参考https://km.glodon.com/pages/viewpage.action?pageId=37652643
        /// \param[out] pGraphicsNodeIdAsker   拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param[in]  planes                 截面坐标系
        /// \param[in]  sections               截面多边形
        /// \param[in]  mode                   顶点匹配模式
        /// \param[in]  isLinear               侧边是否生成为直线
        /// \param[in]  minSegmentLength       极小段距离(参考值1)
        /// \param[in]  distEpsilon            距离容差(参考值Constants::LENGTH_EPS)
        /// \param[out] pErrorCode            错误码
        /// \param[out] opFaceToPathProfileIndexMap  Face索引与两侧截面轮廓索引的关系数据
        /// \return  多截面放样体
        static OwnerPtr<IBody> CreateMultiSectionLoftBody(
            IGraphicsNodeIdAsker*                  pGraphicsNodeIdAsker,
            const std::vector<Coordinate3d>&       planes,
            const std::vector<const IPolygon*>&    sections,
            const MultiSectionLoftVertexMatchMode& mode,
            bool                                   isLinear,
            double                                 minSegmentLength,
            double                                 distEpsilon,
            MultiSectionLoftErrorCode*             pErrorCode = nullptr,
            OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>& opFaceToPathProfileIndexMap = OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>(nullptr)
        );

        /// \brief 创建多截面放样体（使用顶点匹配关系）
        ///
        /// 可参考https://km.glodon.com/pages/viewpage.action?pageId=37652643
        /// \param[out] pGraphicsNodeIdAsker    拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param[in]  planes                  截面坐标系
        /// \param[in]  sections                截面多边形
        /// \param[in]  verticesMap             顶点匹配关系
        /// verticesMap 截面顶点匹配关系, 是一个二维数组, 必须封闭：
        /// 外面的数组索引是各组匹配关系的索引；
        /// 里面的数组索引是各个轮廓的环的索引；
        /// 里面的数组的值是相同或者相邻的顶点索引；
        /// 比如底部轮廓的第一个环上有3个点，中部轮廓的第一个环上有3个点，顶部轮廓的第一个环上有3个点，
        /// 第一个环合法的定点map可以是(0,0,0), (1,1,1), (2,2,2), (0,0,0)；
        /// 当然也可以是(0,1,0), (1,2,1), (2,0,2), (0,1,0)等等；
        /// \param[in]  isLinear                侧边是否生成为直线
        /// \param[in]  minSegmentLength        极小段距离(参考值1)
        /// \param[in]  distEpsilon             距离容差(参考值Constants::LENGTH_EPS)
        /// \param[out] pErrorCode            错误码
        /// \param[out] opFaceToPathProfileIndexMap  Face索引与两侧截面轮廓索引的关系数据
        /// \return 多截面放样体
        static OwnerPtr<IBody> CreateMultiSectionLoftBody(
            IGraphicsNodeIdAsker*                pGraphicsNodeIdAsker,
            const std::vector<Coordinate3d>&     planes,
            const std::vector<const IPolygon*>&  sections,
            const std::vector<std::vector<int>>& verticesMap,
            bool                                 isLinear,
            double                               minSegmentLength,
            double                               distEpsilon,
            MultiSectionLoftErrorCode*             pErrorCode = nullptr,
            OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>& opFaceToPathProfileIndexMap = OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>(nullptr)
        );

        /// \brief 创建多截面放样体（使用闭合点）
        ///
        /// 可参考https://km.glodon.com/pages/viewpage.action?pageId=37652643
        /// \param[out] pGraphicsNodeIdAsker    拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param[in]  planes                  截面坐标系
        /// \param[in]  sections                截面多边形
        /// \param[in]  closedPoints            闭合点
        /// closedPoints 闭合点, 是一个一维数组：
        /// 数组索引是各个轮廓的环的索引；
        /// 数组的值是轮廓的环上顶点索引和顶点参数的数值对；
        /// 比如底部轮廓的第一个环上有3个点，中部轮廓的第一个环上有3个点，顶部轮廓的第一个环上有3个点，
        /// 合法的闭合点可以是(0,0.0), (0,0.0), (0,0.0)；
        /// 当然也可以是(0,0.0), (1,0.0), (2,0.0)等等；
        /// \param[in]  mode                    顶点匹配模式
        /// \param[in]  isLinear                侧边是否生成为直线
        /// \param[in]  minSegmentLength        极小段距离(参考值1)
        /// \param[in]  distEpsilon             距离容差(参考值Constants::LENGTH_EPS)
        /// \param[out] pErrorCode            错误码
        /// \param[out] opFaceToPathProfileIndexMap  Face索引与两侧截面轮廓索引的关系数据
        /// \return 多截面放样体
        static OwnerPtr<IBody> CreateMultiSectionLoftBody(
            IGraphicsNodeIdAsker*                      pGraphicsNodeIdAsker,
            const std::vector<Coordinate3d>&           planes,
            const std::vector<const IPolygon*>&        sections,
            const std::vector<std::pair<int, double>>& closedPoints,
            const MultiSectionLoftVertexMatchMode&     mode,
            bool                                       isLinear,
            double                                     minSegmentLength,
            double                                     distEpsilon,
            MultiSectionLoftErrorCode*             pErrorCode = nullptr,
            OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>& opFaceToPathProfileIndexMap = OwnerPtr<IMultiSectionLoftFaceToPathProfileIndexMap>(nullptr)
        );

        /// \brief 构造螺旋体
        /// \param pGraphicsNodeIdAsker 拓扑命名查询器        
        /// \param pSection             草图截面,不同于扫描，其Y方向始终对应螺旋线坐标系的Z轴
        /// \param sketchCrvIndices     草图线的唯一序号
        /// \param coordinate           螺旋线路径所在的局部坐标系
        /// \param spiralRadiusStart    螺旋线路径的起始半径, 必须大于0
        /// \param spiralRadiusEnd      螺旋线路径的终止半径, 必须大于0
        /// \param spiralAngle          螺旋角度，弧度表示，必须大于0
        /// \param height               螺旋线路径的高度，原则上如果是等半径螺旋，高度不能为0（这种情形应该用回转体来做）
        /// \param clockwise            旋转方向, true : 顺时针, false : 逆时针
        /// \return 螺旋体
        static OwnerPtr<IBody> CreateSpiralBody(
            IGraphicsNodeIdAsker*         pGraphicsNodeIdAsker,
            const IPolygon*               pSection,            
            const std::vector<Int32>&     sketchCrvIndices,
            const Coordinate3d&           coordinate,
            double                        spiralRadiusStart,
            double                        spiralRadiusEnd,
            double                        spiralAngle,
            double                        height,
            bool                          clockwise
        );

        /// \brief 构造沿一串相互连接的空间曲线扫描的扫描壳体
        /// \param connectedCurves           草图截面（首尾相连的二维曲线，与路径切向垂直）
        /// \param pCurve3ds                 扫略路径(一组至少G0连接的空间曲线，目前只支持直线和圆弧)
        /// \param referenceDirection        参考方向
        /// \return 扫描体
        static OwnerPtr<IBody> CreateShell(
            const std::vector<OwnerPtr<ICurve2d>>& connectedCurves,
            const std::vector<const ICurve3d*>& pCurve3ds,
            const Vector3d& referenceDirection);

        /// \brief  由给定拓扑面生成壳体，做深拷贝，默认给定的Face是合法的，不做拓扑多边形位于曲面参数域内的安全检查
        /// \param pIFace 拓扑面，函数内会做深拷贝
        /// \return 壳体
        static OwnerPtr<IBody> CreateShell(const IFace* pIFace);

        /// \brief  由给定的曲面和参数域（多边形定义）创建一个Shell
        /// \param pISurface          曲面，函数内会做深拷贝
        /// \param pIPolygon          多边形
        /// \param isSameDir          = true face的方向是否与surface中一致
        /// \param isStichShell       = false  是否缝合pResultBody与保留面的重合边，默认为false。注意保留面之间重合边默认就是缝合的
        /// \return 壳体
        static OwnerPtr<IBody> CreateShell(
            const ISurface* pISurface,
            const IPolygon* pIPolygon,
            bool isSameDir = true,
            bool isStichShell = false
        ); 

        /// \brief  由给定实体及需要保留的面序号，生成保留的面组成的壳体，做深拷贝
        /// \param pSourceBody    原实体
        /// \param faceIndex      要求保留的面集合，函数内会对该参数做修改，排序，去重等
        /// \return 壳体
        static OwnerPtr<IBody> CreateShell(const IBody* pSourceBody, const std::vector<int>& faceIndex);

        /// \brief  由给定一个或多个三维多段线生成壳体
        /// \param[in] pPolyCurve3ds  每个三维多段线要求有序的首尾连续且封闭，三维边线两两之间不相交并且无自交
        /// \param[out] resultBody  构造的壳体
        /// \return 构造壳体错误类型
        static ShellErrorStatus CreateShell(const std::vector<const IPolyCurve3d*>& pPolyCurve3ds, OwnerPtr<IBody>& resultBody);

        /// \brief  根据给定点坐标构造单点体
        /// \param[in] point  点坐标
        /// \param[out] opAcornBody  创建的单点体
        /// \return 错误码
        static GeometryErrorCode MakeAcornBody(const Vector3d& point, OwnerPtr<IBody>& opAcornBody);

        /// \brief  由一组拓扑边构造线框体
        /// \param[in] edges  输入边集合
        /// \param[out] opWireBody  创建的wirebody
        /// \return 错误码
        static GeometryErrorCode MakeWireBody(const std::vector<const IEdge*>& edges, OwnerPtr<IBody>& opWireBody);

        /// \brief  由一组三维多段线构造线框体
        /// \param[in] pPolyCurve3ds  一组三维多段线
        /// \param[out] opWireBody  创建的wirebody
        /// \return 错误码
        static GeometryErrorCode MakeWireBody(const std::vector<const IPolyCurve3d*>& pPolyCurve3ds, OwnerPtr<IBody>& opWireBody);

        /// \brief  由给定线框体构造壳体，要求线框是闭合的
        /// \param[in] pWireBody  线框体
        /// \param[out] opSheetBody  创建的壳体
        /// \return 错误码
        static GeometryErrorCode MakeSheetBody(const IBody* pWireBody, OwnerPtr<IBody>& opSheetBody);

        /// \brief  构造土方放坡体
        /// \param  pPlane               平面
        /// \param  pPolygon             下底面轮廓
        /// \param  height               高度
        /// \param  widths               每条边的放坡宽度,存储的对象个数应该与pPolygon里所有边的数目总和一样（所有polycurve里的所有曲线）
        /// \return 土方放坡体
        static OwnerPtr<IBody> CreateEarthworkSlope(const IPlane* pPlane, const IPolygon* pPolygon, double height, const std::vector<double>& widths);

        /*!
        *@brief  创建mesh
        *@param[in] const std::vector<Vector3d>& vertices        顶点的数组
        *@param[in] const std::vector<Vector3d>& vertexNormals   顶点法向的数组
        *@param[in] const std::vector<Vector2d>& vertexUVs             纹理坐标的数组
        *@param[in] const std::vector<int>& triangleVertexIndices  顶点索引，每三个索引一组作为三角片
        *@param[in] const std::vector<int>& triangleVertexNormalIndices   顶点法向索引，每三个索引一组作为三角片
        *@param[in] const std::vector<int>& triangleVertexUVIndices   纹理坐标的索引，每三个索引一组作为三角片
        *@return OwnerPtr<IMesh>
        */
        static  OwnerPtr<IMesh> CreateMesh(const std::vector<Vector3d>& vertices,
            const std::vector<Vector3d>& vertexNormals,
            const std::vector<Vector2d>& vertexUVs,
            const std::vector<int>& triangleVertexIndices,
            const std::vector<int>& triangleVertexNormalIndices,
            const std::vector<int>& triangleVertexUVIndices);

        /// \brief  构造附着体
        /// \param  pBodyToAttach              附着前的体
        /// \param  faceIndexToAttach          面在待附着体里的索引，该面将会沿着给定方向，附着到给定目标壳体
        /// \param  pTargetShellBody           附着的目标壳体, 使用者需保证目标壳体中的所有边、面的编号不能重复，否则附着后的体中可能存在重复的编号
        /// \param  direction                  附着方向
        /// \param  pGraphicsNodeIdAsker       拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param  pTargetShellBodyAuxKey     关于目标壳体的、并协助生成拓扑命名的辅助值。如果不提供，同一个体经过多次附着之后，生成新体的边面可能存在重号的可能
        /// \return 新生成的附着后的形体
        static OwnerPtr<IBody> CreateAttachment(const IBody* pBodyToAttach, int faceIndexToAttach, const IBody* pTargetShellBody,
            const Vector3d& direction, IGraphicsNodeIdAsker* pGraphicsNodeIdAsker = nullptr, const int* pTargetShellBodyAuxKey = nullptr);
  
        /// \brief  多目标面构造附着体
        /// \param  pBodyToAttach              附着前的体
        /// \param  faceIndexToAttach          面在待附着体里的索引，该面将会沿着给定方向，附着到给定目标壳体
        /// \param  targetShellBodys           附着的目标壳体集，使用者需保证每个目标壳体中的所有边、面的编号不能重复（不同壳体之间可以存在重复的编号），否则附着后的体中可能存在重复的编号
        /// \param  direction                  附着方向
        /// \param  pGraphicsNodeIdAsker       拓扑命名查询器(输入空指针，则不生成拓扑命名数据(包括Face,Edge的Id))
        /// \param  pTargetShellBodyAuxKeys    关于目标壳体的、并协助生成拓扑命名的辅助值。如果不提供，同一个体经过多次附着之后，生成新体的边面可能存在重号的可能
        /// \return 新生成的附着后的形体
        static OwnerPtr<IBody> CreateAttachment(const IBody* pBodyToAttach, int faceIndexToAttach, const std::vector<const IBody*>& targetShellBodys,
            const Vector3d& direction, IGraphicsNodeIdAsker* pGraphicsNodeIdAsker = nullptr, const std::vector<int>* pTargetShellBodyAuxKeys = nullptr);

        /// \brief  构造集水坑附着体（创建集水坑附着体专门为BIMMAKE的集水坑附着使用，附着规则与一般的墙体附着规则不同）
        ///         当目标面边界既投影不到附着面，附着面侧面又延伸不到目标面时，集水坑附着能够附着成功（一般墙体附着失败））
        ///         该接口不支持编码编号
        /// \param  pBodyToAttach              附着前的体
        /// \param  faceIndexToAttach          面在待附着体里的索引，该面将会沿着给定方向，附着到给定目标壳体
        /// \param  targetShellBodys           附着的目标壳体集
        /// \param  direction                  附着方向
        /// \return 新生成的附着后的形体
        static OwnerPtr<IBody> CreateSumpAttachment(const IBody* pBodyToAttach, int faceIndexToAttach, const std::vector<const IBody*>& targetShellBodys, const Vector3d& direction);

        /// \brief   曲面缝合成体，要求不同曲面完全封闭成体
        ///
        /// \param  surfaces       曲面
        /// \param dDistanceEpsilon  距离容差
        /// \return 缝合的体
        static OwnerPtr<IBody> StitchSurfaces(const std::vector<OwnerPtr<ISurface>>& surfaces, double dDistanceEpsilon = 0.1);

        /// \brief   拓扑面缝合成体，要求拓扑面存在重合边的情况
        ///
        /// 若需要翻转面的朝向，需保证输入数据具备以下条件：
        ///      1.index = 0数据的朝向为基准，保持不变;
        ///      2.索引号为index的数据需要与前index - 1个数据的缝合结果具有重合边
        ///      3.前index - 1个数据的缝合结果为单连通，否则可能翻转失败
        /// \param  inputFaces       输入的待缝合的面
        /// \param dDistanceEpsilon  缝合容差
        /// \param[out] resultBody  缝合的体
        /// \param  bNeedReverseDir 是否翻转输入面的方向。默认faces的朝向一致，不需要反转。若需要翻转面的朝向，则传入参数true
        /// \return 错误码
        static   StitchErrorCode StandardStitchFaces(const std::vector<const IFace*>& inputFaces, double dDistanceEpsilon, OwnerPtr<IBody>& resultBody, bool bNeedReverseDir = false);

     };
}
